package level;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import org.omg.PortableInterceptor.SUCCESSFUL;

import entity.lemming.*;
import entity.lemming.animation.Crushed;
import entity.lemming.animation.Faller;
import entity.lemming.animation.Homie;
import entity.terrain.Terrain;

 

/************************************************************************************
 * 			POSSIBLY NOT FINAL DESIGN: LINKEDLIST IN PLACE OF ARRAYS				*
 * 																					*
 * May have allow for a lemmings backup ability as for climbing, floating ...		*
 ************************************************************************************/ 


/** 
 * A Lemming manager, responsible for resolving events invobylving 
 * Lemmings. Handles the morphing of Lemming types, collision, actions and 
 * the (alive) status of the Lemmings.
 * 
 * @author Neil Cowzer, Olga Murdoch
 */
public class Manager{
	/** An array of Lemmings to be managed. */
	private Lemming[] lemmings;
	/*@ invariant
		lemmings != null
		&&
		(\forall int i; 0 <= i && i < lemmings.length;
		; lemmings[i].getParent() == this);
	@*/
	private boolean used;

	/** The current Level of the Lemming */
	private Level level;
	
	/** The current number of Lemmings alive */
	private int alive;
	/*@ invariant 0 <= alive &&
					   alive >= loaded;
	@*/
	
	/** The current number of Lemmings saved*/
	private int saved;
	/*@ invariant 0 <= saved &&
	   				   saved <= alive;
	@*/
	
	/** The current status of the game */
	private boolean gameOver;
	//@ invariant (gameOver == true && alive == 0) || gameOver == false; 
	
	/** Success of the game */
	private boolean success = false;
	
	/** The current number of lemmings loaded. */
	private int loaded;
	/*@ invariant 0 <= loaded &&
	 				   loaded <= lemmings.length;
	@*/ 
	
	/** Delays the dropping in of the indivual lemmings */
	private int timer;
	//@ invariant timer >= 10;
	
	/** the exit area */
	private Rectangle exit;
	
	private int mouseXco;
	private int mouseYco;
	
	private String lemmingEvent;
	
	/**
	 * Create an instance of LemmingManager.
	 * 
	 * @param numOfLemmings the number of Lemmings in the level.
	 */
	/*@ requires numOfLemmings > 0 && level != null;
		assignable lemmings && level && alive && gameOver && loaded;
		ensures gameOver == false;
	@*/
	public Manager(int numOfLemmings, Level level){
		
		lemmings = new Lemming[numOfLemmings];
		this.level = level;
		this.alive = 0;
		this.saved = 0;
		
		// Ensure game is not over
		gameOver = false;
		loaded = 0;
		timer = 10;
		
		exit = new Rectangle(level.getMap().getEndX(),level.getMap().getEndY(), level.getMap().getEndX()+1, level.getMap().getEndY()+1);
	} 
	
	/**
	 * Perform the logic of this game. Make each Lemming move once and 
	 * resolve any events accordingly.
	 */
	public void play(){
		try {
			Terrain terrain = level.getMap().getTerrain();
			if (lemmingEvent == "Paws"){
				// do nothing just pause!!!
			}else if (lemmingEvent == "Nuke"){
				for (int i = 0; i < lemmings.length; i++){
					if (lemmings[i] != null){
						if (lemmings[i].isAlive()){
							// get the lemmings direction
							int x = lemmings[i].getSpeed_X();
							int y = lemmings[i].getSpeed_Y();
							
							if (!(lemmings[i] instanceof Bomber)){
								String type = "";
								if (lemmings[i] instanceof Blocker){
									type = "Blocker";
								} else{
									type = "Walker";
								}
								
								lemmings[i] = new Bomber(lemmings[i].center(), type);
								if (x < 0){
									lemmings[i].turnAround();
								}
								

							}else if (lemmings[i] != null){
								lemmings[i].move(terrain);

								for (int j = 0; j < lemmings.length; j++){
									if (lemmings[j] != null){
										if (lemmings[i].collision(lemmings[j])){
											lemmings[i].turnAround();
										}
									}
								}
							}
						}else if (!lemmings[i].isAlive()){
							lemmings[i] = null;
							alive--;
						}
					}
				}
			}else{


				if (alive < lemmings.length && loaded < lemmings.length && timer++%20 == 0){
					start();
				}

				for (int i = 0; i < lemmings.length; i++){
					if (lemmings[i] != null){
						if (!(lemmings[i] instanceof Bomber)){
					
						int x = lemmings[i].getSpeed_X();
						int y = lemmings[i].getSpeed_Y();


						if((mouseXco <= (lemmings[i].getBounds().x + 6))&& (mouseXco >= lemmings[i].getBounds().x )&& (mouseYco <=(lemmings[i].getBounds().y + 10)) && (mouseYco >= lemmings[i].getBounds().y)){
							//System.out.println("match");
							mouseXco = -1;
							mouseYco = -1;
							if (lemmings[i] instanceof Walker){
								if(lemmingEvent == "Digger"){
									lemmings[i] = new Digger(lemmings[i].center());
									lemmings[i].setOldSpeed(x, y);
									used = true;
									
								}
								else if(lemmingEvent == "Blocker"){
									lemmings[i] = new Blocker(lemmings[i].center());
									used = true;
								}
								else if(lemmingEvent == "Climber"){
									lemmings[i] = new Climber(lemmings[i].center());
									lemmings[i].setOldSpeed(x, y);
									used = true;
									
									if (x<0){
										lemmings[i].turnAround();
									}
								}
								else if(lemmingEvent == "Basher"){
									lemmings[i] = new Basher(lemmings[i].center());
									used = true;
									if (x < 0){
										lemmings[i].turnAround();
									}
									lemmings[i].setOldSpeed(x, y);
								}
								else if(lemmingEvent == "Builder"){
									//lemmings[i] = new Bridger(lemmings[i].center());
									//lemmings[i].setOldSpeed(x, y);
									used = true; 
								}
								else if(lemmingEvent == "Bomber"){
									String type;
									if (lemmings[i] instanceof Blocker){
										type = "Blocker";
									} else{
										type = "Walker";
									}
									lemmings[i] = new Bomber(lemmings[i].center(), type);
									used = true;
									if (x < 0){
										lemmings[i].turnAround();
									}
								}
								else if(lemmingEvent == "Miner"){
									lemmings[i] = new Miner(lemmings[i].center());
									lemmings[i].setOldSpeed(x, y);
									if (x < 0){
										lemmings[i].turnAround();
									}
									used = true;
								}
							}
							if(lemmings[i] instanceof Faller && lemmingEvent == "Floater"){
								lemmings[i] = new Floater(lemmings[i].center());
								lemmings[i].setOldSpeed(x, y);
								used = true;
							}
						}

						// actual lemming controls
						lemmings[i].move(terrain);

						for (int j = 0; j < lemmings.length; j++){
							if (lemmings[j] != null){
								if (lemmings[i].collision(lemmings[j])){
									lemmings[i].turnAround();
								}
							}
						}

						// Check has the Lemming reached the exit
						//if(exit.contains(lemmings[i].center())){
						if(lemmings[i].getBounds().intersects(exit.getBounds())){
							if (lemmings[i] instanceof Homie){
								if (lemmings[i].saved()){
									//lemmings[i] = null;
									saved++;
									lemmings[i] = null;
									alive--;
								}
								
							}
							else{
								lemmings[i] = new Homie(level.getMap().getEndX(),level.getMap().getEndY());
							}
							
						}
						
						else if (lemmings[i].crush()){
							lemmings[i] = new Crushed(lemmings[i].center());
						}
						
						else if (lemmings[i].fall()){
							//x = lemmings[i].getOldSpeed_X();
							lemmings[i] = new Faller(lemmings[i].center());

							// special case for storing its old speed, it needs to store the old, old x speed
							lemmings[i].setOldSpeed(x, y);

							if (x < 0){
								lemmings[i].turnAround();
							}
						}
						
						else if (lemmings[i].energy() == 0){
							// Convert back to a walker
							if (lemmings[i].getOldSpeed_X() < 0){
								lemmings[i] =  new Walker(lemmings[i].center());
								lemmings[i].turnAround();
							}
							else {
								lemmings[i] =  new Walker(lemmings[i].center());
							}
						}
						
						else if (!lemmings[i].isAlive()){
							lemmings[i] = null;
							alive--;
						}
						
						if (lemmings[i] != null){
							if (lemmings[i].getX() < -10 || lemmings[i].getX() > 330 || lemmings[i].getY() < -10 || lemmings[i].getY() > 210){
								lemmings[i] = null;
								alive--;
							}
						}

					}
					}
				}
			}
			// If there are no lemmings => GAMEOVER
		}catch (Exception e){

		}
		if (alive == 0 && loaded == lemmings.length){
			gameOver = true;
			level.stopMusic();
		}
		
		if (saved >= level.getGoal().getNum2Save()){
			success = true;
		}

	}
	
	/**
	 * Create the new Lemmings as needed.
	 * New Lemmings at start of each level are fallers
	 */
	/*@ ensures alive == \old(alive) + 1 &&
	 			loaded == \old(loaded) + 1;
	@*/
	public void start(){
		//lemmings[alive] = new Digger(level.getMap().getStartX(), level.getMap().getStartY());
		lemmings[alive] = new Faller(level.getMap().getStartX(), level.getMap().getStartY());
		alive++;
		loaded++;
	}
	
	/**
	 * Draw the Lemmings & Level to the Screen.
	 * 
	 * @param g
	 */
	public void draw(Graphics g){
		level.getMap().draw(g);
		for (int i = 0; i < lemmings.length; i++){
			if (lemmings[i] != null){
				lemmings[i].draw(g);
			}
		}
		//lemming1.draw(g);
	}
	
	/**
	 * Retrieve the array of Lemmings.
	 * 
	 * @return a an array of Lemmings.
	 */
	public /*@ pure @*/ Lemming[] getLemmings(){
		return lemmings;
	}
	
	// Possibly replace by a success or failure check!!!!!!
	/**
	 * Check to see if the game is over.
	 * 
	 * @return True if the game is over.
	 */
	public /*@ pure @*/ boolean gameOver(){
		return gameOver;
	}
	
	public void mouseEvents(String lemming){	
		lemmingEvent = lemming;	
	}
	
	public boolean successful(){
		return success;
	}
	
	public int getAlive(){
		return alive;
	}
	
	public int getSaved(){
		return saved;
	}
	
	public int percentage(){
		return (int)((float)(saved)/lemmings.length *100);
	}
	
	public void setMouseCoordinates(int Xco, int Yco){
		mouseXco = Xco;
		mouseYco = Yco;
		
	}
	
	public boolean eventUsed(){
		return used;
	}
	public void setUnUsed(){
		used = false;
	}

	
	/**
	 * Handle the cursor positon and events accordingly.
	 * 
	 * @param y the X-coordinate of the cursor.
	 * @param x the Y-coordinate of the cursor.
	 * @param lemming a Lemming Object.
	 */
	//@	requires lemming != null && x >= 0 && y >= 0;
/*	private void mouseEvent(Lemming lemming, int x, int y){
		// only act if over a Lemming, otherwise ignore
		//for (int i = 0; i < lemmings.length; i++){
			if (lemming != null){
				// Is it over a lemming?
				if (lemming.getBounds().intersectsLine(x, y, x, y)){
					// Change to cursor....
					System.out.println("over a lemming");
				}
			}
		//}
	} */

	
}
